﻿using System;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;
using Unity;

namespace Ioc.Unity
{
    /// <summary>
    /// Unity容器
    /// </summary>
    public class UnityDIContainer : IServiceProvider, IDisposable
    {
        #region 资源释放相关        
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing">是否是释放托管资源</param>
        protected virtual void Dispose(bool disposing)
        {
            // 暂不处理非托管资源，因为没有托管资源，这里不管是析构函数还是主动释放，都释放container
            try
            {
                container.Dispose();
                container = null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 析构函数，在对象不可访问时触发
        /// </summary>
        ~UnityDIContainer()
        {
            Dispose(false);
        }
        #endregion

        #region 单例模式
        /// <summary>
        /// Unity容器
        /// </summary>
        private IUnityContainer container;

        /// <summary>
        /// 单例
        /// </summary>
        private static readonly UnityDIContainer instance = new UnityDIContainer();

        /// <summary>
        /// 对象锁
        /// </summary>
        private static object objLock = new object();

        /// <summary>
        /// 构造函数
        /// </summary>
        private UnityDIContainer()
        {
            // 获取unity配置节点
            var configSection = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);

            container = new UnityContainer();

            // 根据节点配置容器
            configSection.Configure(container, "unityContainer");
        }
        #endregion

        /// <summary>
        /// 获取容器
        /// </summary>
        public static UnityDIContainer DIContainer
        {
            get
            {
                if (instance == null)
                {
                    lock (objLock)
                    {
                        //如果类的实例不存在则创建，否则直接返回
                        if (instance == null)
                            return new UnityDIContainer();
                    }
                }
                return instance;
            }
        }

        /// <summary>
        /// 根据给出的接口类型获取实现类
        /// </summary>
        /// <typeparam name="T">接口的类型</typeparam>
        /// <returns>实现接口的对象实例</returns>
        public T GetInjectionInstance<T>()
        {
            return container.Resolve<T>();
        }

        /// <summary>
        /// 获取实现类型
        /// </summary>
        /// <param name="serviceType">接口类型</param>
        /// <returns>接口实现实例</returns>
        public object GetService(Type serviceType)
        {
            return container.Resolve(serviceType);
        }
    }
}
